﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Data;
using System.Collections.ObjectModel;
using System.Text.RegularExpressions;

namespace UmlControlLibrary
{
    public class DiagramElement : UmlElement
    {
        public class Events
        {
            public static Event InheritanceModified = new Event("Inheritance" + Event.Modified, typeof(UmlElement));
        }

        public string MyName
        {
            get
            {
                return (string.IsNullOrEmpty(_stereotype) ? "" : "<" + _stereotype + ">") + Name + (string.IsNullOrEmpty(_parent) ? "" : ":" + _parent);
            }
            set
            {
                Regex regexObj = new Regex("^(<(?<stereotype>.+?)>)?(?<name>.*?)(:(?<parents>.+))?$", RegexOptions.IgnorePatternWhitespace);
                Stereotype = regexObj.Match(value).Groups["stereotype"].Value.Trim();
                Parent = regexObj.Match(value).Groups["parents"].Value.Trim();
                base.Name = regexObj.Match(value).Groups["name"].Value.Trim();
                OnPropertyChanged("Name");
            }
        }

        private string _stereotype;
        public string Stereotype
        {
            get
            {
                if ((_stereotype != null) && (_stereotype != ""))
                    return "« " + _stereotype + " »";
                else
                    return "";
            }
            set { 
                _stereotype = value;
                OnPropertyChanged("Stereotype");
            }
        }

        private string _parent;
        public string Parent
        {
            get
            {
                if (_parent == null) _parent = "";
                return _parent;
            }
            set { 
                _parent = value;
                OnPropertyChanged("Parent");
                EventService.BroadcastEvent(this, DiagramElement.Events.InheritanceModified);
            }
        }

        public ObservableCollection<UmlElement> links = new ObservableCollection<UmlElement>();

        public virtual void Link(UmlElement element2)
        {
            links.Add(element2);
            OnPropertyChanged("Childs");
        }
        
        private static Dictionary<Type, ControlTemplate> Templates = new Dictionary<Type, ControlTemplate>();
        protected virtual ControlTemplate GetTemplate()
        {
            return null;
        }

        protected static ControlTemplate DiagramElementTemplateFactory(Type type)
        {
            ControlTemplate t = new ControlTemplate(typeof(Control));
            FrameworkElementFactory grid = new FrameworkElementFactory(typeof(Grid));
            t.VisualTree = grid;

            FrameworkElementFactory classControl = new FrameworkElementFactory(type);
            classControl.Name = type.Name+"View";
            classControl.SetValue(Control.VerticalAlignmentProperty, VerticalAlignment.Stretch);
            classControl.SetValue(Control.VerticalContentAlignmentProperty, VerticalAlignment.Stretch);
            classControl.SetValue(Control.HorizontalAlignmentProperty, HorizontalAlignment.Stretch);
            classControl.SetValue(Control.HorizontalContentAlignmentProperty, HorizontalAlignment.Stretch);
            classControl.SetValue(Control.MarginProperty, new Thickness(6));
            classControl.SetBinding(Control.DataContextProperty, new Binding("DataContext"));
            
            grid.AppendChild(classControl);
            return t;
        }

        public ControlTemplate GetElementTemplate()
        {
            Type type = this.GetType();
            if (Templates.ContainsKey(type))
                return Templates[type];
            else
                return null;
        }

        public DiagramElement(string name):base(name)
        {
            Type type = this.GetType();
            if (!Templates.ContainsKey(type))
                Templates.Add(type, GetTemplate());
        }



        #region UmlElement Members

        public override ObservableCollection<UmlElement> GetChilds()
        {
            ObservableCollection<UmlElement> elements = base.GetChilds();
/*            foreach (UmlElement de in links)
                if (de is DiagramElement)
                    elements.Add(de);
            foreach (UmlElement de in links)
                if (de is UmlRelation)
                    elements.Add(de);*/
            return elements;
        }
        #endregion
    }
}
